package com.im.util;

import com.im.common.ClientLinkInfo;
import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.apache.commons.lang.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @Author: szw
 * @Date: 2020/5/22 17:22
 */
public class ConstantUtil {

    /**
     * 定义channel集合,管理channel,传入全局事件执行器
     */
    private static ChannelGroup GROUP = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    public static String TARGET_ID = "--";

    public synchronized static void addGROUP(Channel channel) {
        if (!GROUP.contains(channel)) {
            GROUP.add(channel);
        }
    }
    public static void pushAll(String message) {
        GROUP.writeAndFlush(new TextWebSocketFrame(message));
    }
    public static ChannelGroup getAllChannel() {
        return GROUP;
    }

    //  <clientId, [targetId, channel]>
    private static volatile Map<String, List<ClientLinkInfo>> MANAGER = new ConcurrentHashMap<>();

    public static void put(String clientId, String targetId, Channel channel) {
        if (StringUtils.isBlank(targetId)) {
            targetId = TARGET_ID;
        }
        List<ClientLinkInfo> linkInfoList = MANAGER.get(clientId);
        if (linkInfoList == null) {
            linkInfoList = new ArrayList<>();
        }
        String channelId = channel.id().asLongText();
        // 添加客户端连接信息
        ClientLinkInfo linkInfo = ClientLinkInfo.builder()
                .channel(channel)
                .targetId(targetId)
                .channelId(channelId)
                .build();

        // 同一个客户端只能有一个连接 相同的客户端接入会移除旧的连接  避免一个客户端创过多连接耗尽资源
        String finalTargetId = targetId;
        List<ClientLinkInfo> remove = linkInfoList.stream().filter(r -> r.getTargetId().equals(finalTargetId)).collect(Collectors.toList());
        for (ClientLinkInfo re : remove) {
            Channel chan = re.getChannel();
            chan.close();
        }
        linkInfoList.removeAll(remove);
        linkInfoList.add(linkInfo);
        // List<ClientLinkInfo> list = linkInfoList.stream().distinct().collect(Collectors.toList());

        MANAGER.put(clientId, linkInfoList);
    }

    public static Map<String, List<ClientLinkInfo>> get() {
        return MANAGER;
    }

    public static Optional<List<ClientLinkInfo>> get(String clientId) {
        //根据 clientId 获取对应的channel
        return Optional.ofNullable(MANAGER.get(clientId));
    }

    /**
     * 根据客户端id与目标客户端id获取通道
     * @param clientId 客户端id
     * @param targetId 标客户端id
     * @return ClientLinkInfo
     */
    public static Optional<ClientLinkInfo> get(String clientId, String targetId) {
        //根据 clientId 获取对应的channel
        Optional<List<ClientLinkInfo>> clientLinkInfos = get(clientId);
        return clientLinkInfos.orElse(new ArrayList<>()).stream().filter(f -> f.getTargetId().equals(targetId)).findFirst();
    }

    public static String getClientId(String channelId) {
        //根据 channelId 获取对应的 userId
        for (Map.Entry<String, List<ClientLinkInfo>> entry : MANAGER.entrySet()) {
            Optional<ClientLinkInfo> first = entry.getValue().stream().filter(f -> f.getChannelId().equals(channelId)).findFirst();
            if (first.isPresent()) {
                return entry.getKey();
            }
        }
        return null;
    }

    /**
     * 所有客户端id
     * @return List<String>
     */
    public static List<String> getClients() {
        return new ArrayList<>(MANAGER.keySet());
    }

    /**
     * 移除该用户所有连接
     */
    public  static void remove(String clientId) {
        //根据 clientId 获取对应的channel
        MANAGER.remove(clientId);
    }

    /**
     * 根据channelId删除
     */
//    public  static void remove(String channelId, String userId) {
//        MANAGER.forEach((k, v) ->{
//            if (v.getChannel().id().asLongText().equals(channelId)) {
//                remove(k);
//            }
//        });
//    }

    public  static void remove(String clientId, String targetId) {
        MANAGER.get(clientId).removeIf(m->m.getTargetId().equals(targetId));
    }

    /**
     * 根据channelId删除
     */
    public static void remove(String clientId, Channel channel) {
        // 删除对应客户端的连接
        List<ClientLinkInfo> list = MANAGER.get(clientId);
        list.removeIf(m -> m.getChannel().id().asLongText().equals(channel.id().asLongText()));
        if (list.isEmpty() || MANAGER.get(clientId).isEmpty()) {
            remove(clientId);
        }
    }

    public static void remove(Channel channel) {
        // 删除对应客户端的连接
        String channelId = channel.id().asLongText();
        String clientId = getClientId(channelId);
        GROUP.remove(channel);
        if (StringUtils.isBlank(clientId)) {
            return;
        }
        List<ClientLinkInfo> list = MANAGER.get(clientId);
        if (list == null || list.isEmpty()) {
            remove(clientId);
            return;
        }
        list.removeIf(m -> m.getChannel().id().asLongText().equals(channelId));
        if (list == null || list.isEmpty()) {
            remove(clientId);
        }
    }

}
